/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.iotdb.db.mpp.plan.execution.config;

import org.apache.iotdb.db.mpp.plan.execution.config.metadata.*;
import org.apache.iotdb.db.mpp.plan.execution.config.metadata.template.*;
import org.apache.iotdb.db.mpp.plan.execution.config.sys.*;
import org.apache.iotdb.db.mpp.plan.execution.config.sys.sync.*;
import org.apache.iotdb.db.mpp.plan.statement.Statement;
import org.apache.iotdb.db.mpp.plan.statement.StatementNode;
import org.apache.iotdb.db.mpp.plan.statement.StatementVisitor;
import org.apache.iotdb.db.mpp.plan.statement.metadata.*;
import org.apache.iotdb.db.mpp.plan.statement.metadata.template.*;
import org.apache.iotdb.db.mpp.plan.statement.sys.*;
import org.apache.iotdb.db.mpp.plan.statement.sys.sync.*;
import org.apache.iotdb.tsfile.exception.NotImplementedException;

public class ConfigTaskVisitor
        extends StatementVisitor<IConfigTask, ConfigTaskVisitor.TaskContext> {

    @Override
    public IConfigTask visitNode(StatementNode node, TaskContext context) {
        throw new UnsupportedOperationException(
                "Unsupported statement type: " + node.getClass().getName());
    }

    @Override
    public IConfigTask visitStatement(Statement statement, TaskContext context) {
        throw new NotImplementedException("ConfigTask is not implemented for: " + statement);
    }

    @Override
    public IConfigTask visitSetStorageGroup(SetStorageGroupStatement statement, TaskContext context) {
        return new SetStorageGroupTask(statement);
    }

    @Override
    public IConfigTask visitDeleteStorageGroup(
            DeleteStorageGroupStatement statement, TaskContext context) {
        return new DeleteStorageGroupTask(statement);
    }

    @Override
    public IConfigTask visitShowStorageGroup(
            ShowStorageGroupStatement statement, TaskContext context) {
        return new ShowStorageGroupTask(statement);
    }

    @Override
    public IConfigTask visitCountStorageGroup(
            CountStorageGroupStatement statement, TaskContext context) {
        return new CountStorageGroupTask(statement);
    }

    @Override
    public IConfigTask visitSetTTL(SetTTLStatement statement, TaskContext context) {
        return new SetTTLTask(statement);
    }

    @Override
    public IConfigTask visitUnSetTTL(UnSetTTLStatement statement, TaskContext context) {
        return new UnSetTTLTask(statement);
    }

    @Override
    public IConfigTask visitShowTTL(ShowTTLStatement showTTLStatement, TaskContext context) {
        return new ShowTTLTask(showTTLStatement);
    }

    @Override
    public IConfigTask visitShowCluster(
            ShowClusterStatement showClusterStatement, TaskContext context) {
        if (showClusterStatement.isDetails()) {
            return new ShowClusterDetailsTask(showClusterStatement);
        } else if (showClusterStatement.isParameters()) {
            return new ShowClusterParametersTask();
        } else {
            return new ShowClusterTask(showClusterStatement);
        }
    }

    @Override
    public IConfigTask visitAuthor(AuthorStatement statement, TaskContext context) {
        return new AuthorizerTask(statement);
    }

    @Override
    public IConfigTask visitMerge(MergeStatement mergeStatement, TaskContext context) {
        return new MergeTask(mergeStatement);
    }

    @Override
    public IConfigTask visitFlush(FlushStatement flushStatement, TaskContext context) {
        return new FlushTask(flushStatement);
    }

    @Override
    public IConfigTask visitClearCache(ClearCacheStatement clearCacheStatement, TaskContext context) {
        return new ClearCacheTask(clearCacheStatement);
    }

    @Override
    public IConfigTask visitLoadConfiguration(
            LoadConfigurationStatement loadConfigurationStatement, TaskContext context) {
        return new LoadConfigurationTask(loadConfigurationStatement);
    }

    @Override
    public IConfigTask visitSetSystemStatus(
            SetSystemStatusStatement setSystemStatusStatement, TaskContext context) {
        return new SetSystemStatusTask(setSystemStatusStatement);
    }

    @Override
    public IConfigTask visitCreateFunction(
            CreateFunctionStatement createFunctionStatement, TaskContext context) {
        return new CreateFunctionTask(createFunctionStatement);
    }

    @Override
    public IConfigTask visitDropFunction(
            DropFunctionStatement dropFunctionStatement, TaskContext context) {
        return new DropFunctionTask(dropFunctionStatement);
    }

    @Override
    public IConfigTask visitShowFunctions(
            ShowFunctionsStatement showFunctionsStatement, TaskContext context) {
        return new ShowFunctionsTask();
    }

    @Override
    public IConfigTask visitCreateTrigger(
            CreateTriggerStatement createTriggerStatement, TaskContext context) {
        return new CreateTriggerTask(createTriggerStatement);
    }

    @Override
    public IConfigTask visitDropTrigger(
            DropTriggerStatement dropTriggerStatement, TaskContext context) {
        return new DropTriggerTask(dropTriggerStatement);
    }

    @Override
    public IConfigTask visitShowTriggers(
            ShowTriggersStatement showTriggersStatement, TaskContext context) {
        return new ShowTriggersTask();
    }

    @Override
    public IConfigTask visitShowRegion(ShowRegionStatement showRegionStatement, TaskContext context) {
        return new ShowRegionTask(showRegionStatement);
    }

    @Override
    public IConfigTask visitCreateSchemaTemplate(
            CreateSchemaTemplateStatement createSchemaTemplateStatement, TaskContext context) {
        return new CreateSchemaTemplateTask(createSchemaTemplateStatement);
    }

    @Override
    public IConfigTask visitShowNodesInSchemaTemplate(
            ShowNodesInSchemaTemplateStatement showNodesInSchemaTemplateStatement, TaskContext context) {
        return new ShowNodesInSchemaTemplateTask(showNodesInSchemaTemplateStatement);
    }

    @Override
    public IConfigTask visitShowSchemaTemplate(
            ShowSchemaTemplateStatement showSchemaTemplateStatement, TaskContext context) {
        return new ShowSchemaTemplateTask(showSchemaTemplateStatement);
    }

    @Override
    public IConfigTask visitSetSchemaTemplate(
            SetSchemaTemplateStatement setSchemaTemplateStatement, TaskContext context) {
        return new SetSchemaTemplateTask(setSchemaTemplateStatement);
    }

    @Override
    public IConfigTask visitShowPathSetTemplate(
            ShowPathSetTemplateStatement showPathSetTemplateStatement, TaskContext context) {
        return new ShowPathSetTemplateTask(showPathSetTemplateStatement);
    }

    @Override
    public IConfigTask visitDeactivateTemplate(
            DeactivateTemplateStatement deactivateTemplateStatement, TaskContext context) {
        return new DeactivateSchemaTemplateTask(context.getQueryId(), deactivateTemplateStatement);
    }

    @Override
    public IConfigTask visitUnsetSchemaTemplate(
            UnsetSchemaTemplateStatement unsetSchemaTemplateStatement, TaskContext context) {
        return new UnsetSchemaTemplateTask(context.getQueryId(), unsetSchemaTemplateStatement);
    }

    @Override
    public IConfigTask visitDropSchemaTemplate(
            DropSchemaTemplateStatement dropSchemaTemplateStatement, TaskContext context) {
        return new DropSchemaTemplateTask(dropSchemaTemplateStatement);
    }

    @Override
    public IConfigTask visitShowDataNodes(
            ShowDataNodesStatement showDataNodesStatement, TaskContext context) {
        return new ShowDataNodesTask(showDataNodesStatement);
    }

    @Override
    public IConfigTask visitShowConfigNodes(
            ShowConfigNodesStatement showConfigNodesStatement, TaskContext context) {
        return new ShowConfigNodesTask(showConfigNodesStatement);
    }

    @Override
    public IConfigTask visitShowPipeSink(
            ShowPipeSinkStatement showPipeSinkStatement, TaskContext context) {
        return new ShowPipeSinkTask(showPipeSinkStatement);
    }

    @Override
    public IConfigTask visitShowPipe(ShowPipeStatement showPipeStatement, TaskContext context) {
        return new ShowPipeTask(showPipeStatement);
    }

    @Override
    public IConfigTask visitDropPipe(DropPipeStatement dropPipeStatement, TaskContext context) {
        return new DropPipeTask(dropPipeStatement);
    }

    @Override
    public IConfigTask visitCreatePipeSink(
            CreatePipeSinkStatement createPipeSinkStatement, TaskContext context) {
        return new CreatePipeSinkTask(createPipeSinkStatement);
    }

    @Override
    public IConfigTask visitDropPipeSink(
            DropPipeSinkStatement dropPipeSinkStatement, TaskContext context) {
        return new DropPipeSinkTask(dropPipeSinkStatement);
    }

    @Override
    public IConfigTask visitCreatePipe(CreatePipeStatement createPipeStatement, TaskContext context) {
        return new CreatePipeTask(createPipeStatement);
    }

    @Override
    public IConfigTask visitStartPipe(StartPipeStatement startPipeStatement, TaskContext context) {
        return new StartPipeTask(startPipeStatement);
    }

    @Override
    public IConfigTask visitStopPipe(StopPipeStatement stopPipeStatement, TaskContext context) {
        return new StopPipeTask(stopPipeStatement);
    }

    @Override
    public IConfigTask visitDeleteTimeseries(
            DeleteTimeSeriesStatement deleteTimeSeriesStatement, TaskContext context) {
        return new DeleteTimeSeriesTask(context.getQueryId(), deleteTimeSeriesStatement);
    }

    @Override
    public IConfigTask visitGetRegionId(
            GetRegionIdStatement getRegionIdStatement, TaskContext context) {
        return new GetRegionIdTask(getRegionIdStatement);
    }

    @Override
    public IConfigTask visitGetSeriesSlotList(
            GetSeriesSlotListStatement getSeriesSlotListStatement, TaskContext context) {
        return new GetSeriesSlotListTask(getSeriesSlotListStatement);
    }

    @Override
    public IConfigTask visitGetTimeSlotList(
            GetTimeSlotListStatement getTimeSlotListStatement, TaskContext context) {
        return new GetTimeSlotListTask(getTimeSlotListStatement);
    }

    @Override
    public IConfigTask visitMigrateRegion(
            MigrateRegionStatement migrateRegionStatement, TaskContext context) {
        return new MigrateRegionTask(migrateRegionStatement);
    }

    @Override
    public IConfigTask visitCreateContinuousQuery(
            CreateContinuousQueryStatement createContinuousQueryStatement, TaskContext context) {
        return new CreateContinuousQueryTask(
                createContinuousQueryStatement, context.sql, context.username);
    }

    @Override
    public IConfigTask visitDropContinuousQuery(
            DropContinuousQueryStatement dropContinuousQueryStatement, TaskContext context) {
        return new DropContinuousQueryTask(dropContinuousQueryStatement);
    }

    @Override
    public IConfigTask visitShowContinuousQueries(
            ShowContinuousQueriesStatement showContinuousQueriesStatement, TaskContext context) {
        return new ShowContinuousQueriesTask();
    }

    public static class TaskContext {

        private final String queryId;

        private final String sql;

        private final String username;

        public TaskContext(String queryId, String sql, String username) {
            this.queryId = queryId;
            this.sql = sql;
            this.username = username;
        }

        public String getQueryId() {
            return queryId;
        }

        public String getSql() {
            return sql;
        }

        public String getUsername() {
            return username;
        }
    }
}
